'''

1. __new__ 和 __init__
    __new__ 控制类的创建，必须要有返回值， 创建实例， 先执行， 返回类实例
    __init__ 初始化类属性之类的工作
 1) 单例模式
 2) 工厂模式

2.metaclass 的使用
  在类创建的时候，对类进行一些属性或方法的控制， 类似于函数的装饰器，


'''


''' init 和 new'''
class Person(object):
    def __new__(cls, name, age):
        print('new class')
        print(type(cls))
        return super(Person, cls).__new__(cls)
    def __init__(self, name, age):
        print('init')
        print(type(self))
        super().__init__()
        self.name = name
        self.age = age

person = Person('dsc', 10)
print(type(Person))
print(type(person))
print(person.__dict__)


'''单例模式'''
class Single(object):

    def __new__(Single, *args, **kwargs):
        if not hasattr(Single, '_instance'):
            Single._instance = object.__new__(Single)
            print(type(Single._instance))
        return Single._instance
    def __init__(self):
        print(id(self))

single = Single()
print(single)
single2 = Single()
print(single2)


'''工厂模式'''
class Bean :
    def aa(self):
        pass


class Factory:
    Beans = {}
    def __new__(cls, name, *args, **kwargs):
        if name not in cls.Beans:
            cls.Beans[name] = Bean()
        return cls.Beans[name]
    def __init__(self, name, *args, **kwargs):
        print('init')
b1 = Factory('dsc')
b2 = Factory('dsc')
b3 = Factory('dsc2')
print(b1)
print(b2)
print(b3)


''' 元类 '''
# metaclass是创建类，所以必须从`type`类型派生：
class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type( name, bases, attrs)

class MyList(list, metaclass=ListMetaclass):
    pass# 指示使用ListMetaclass来定制类

l = MyList()
l.add(1)
print(l.__dict__)
print(dir(l))

